/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */

package mundo;

import java.util.Stack;

/**
 * This class puts together the map and the robot, so they are able to interact.
 * 
 * @author JuanFer
 */
public class RobotAndMap
{
    /**
     * North
     */
    public static final int NORTH = 0, SOUTH = 1, WEST = 2, EAST = 3;

    /**
     * Creates a robot.
     */
    public Robot rob;

    /**
     * Map object for the class.
     */
//    public Map place;
    
    public Map place;
    
    

    /**
     * Constructor that sets the map and also sets the initial position.
     * 
     * @param pieces
     * @param x1
     * @param y1
     */
    public RobotAndMap(int pieces[][], int x1, int y1)
    {
    place = new Map(pieces);
    rob = new Robot(x1,y1,3);
	rob.setxCoordinate(x1);
	rob.setyCoordinate(y1);
    }

    /**
     * Constructor that sets the map. Precondition: Robot position is 1,1 and
     * heads north.
     * 
     * @param pieces
     */
    public RobotAndMap(int pieces[][])
    {
	place = new Map(pieces);
	rob = new Robot(1, 1, Robot.north);
    }

    /**
     * Sets robot position to parameters.
     * 
     * @param x1
     * @param y1
     * @return true if new position is valid and set
     */
    public boolean setPosition(int x1, int y1)
    {
	if (!place.place[x1][y1].walkable())
	{
	    return false;
	}
	rob = new Robot(1, 1, 0);
	rob.setxCoordinate(x1);
	rob.setyCoordinate(y1);
	return true;
    }

    /**
     * Retruns robot x coordinate.
     * 
     * @return x coordinate
     */
    public int getX()
    {
	return rob.getxCoordinate();
    }

    /**
     * Returns robot y coordinate.
     * 
     * @return y coordinate
     */
    public int getY()
    {
	return rob.getyCoordinate();
    }

    /**
     * Returns robot position in an array of integers size 2. First position is
     * x coordinate, second position is y coordinate.
     * 
     * @return array of position
     */
    public int[] getPosition()
    {
	int[] position = new int[2];

	position[0] = rob.xCoordinate;
	position[1] = rob.yCoordinate;

	return position;
    }

    /**
     * Returns headsTo parameter.
     * 
     * @return headsTo parameter
     */
    public int getDirection()
    {
	return rob.getHeadsTo();
    }

    /**
     * Sets robot parameter isPainting to true.
     */
    public void paint()
    {
	rob.setIsPainting(true);
    }

    /**
     * Sets robot parameter isPainting to false.
     */
    public void stopPainting()
    {
	rob.setIsPainting(false);
    }

    /**
     * Says if the MapPiece which the robot faces is painted.
     * 
     * @return true if it is painted.
     */
    public boolean nextIsPainted()
    {
	return nextPiece().isPainted();
    }

    /**
     * Says if the MapPiece which teh robot faces is walkable (it is GroundType
     * land).
     * 
     * @return True if next MapPiece is walkable.
     */
    public boolean nextIsWalkable()
    {
	return nextPiece().walkable();
    }

    /**
     * 
     * @return
     */
    public boolean nextHasObject()
    {
	return nextPiece().isHasObj();
    }

    /**
     * Retunrs the MapPiece the robot faces
     * 
     * @return MapPiece toward which robot will move.
     */
    public MapPiece nextPiece()
    {
	if (rob.getHeadsTo() == Robot.east)
	{
	    return place.place[rob.getxCoordinate() + 1][rob.getyCoordinate()];
	}
	if (rob.getHeadsTo() == Robot.north)
	{
	    return place.place[rob.getxCoordinate()][rob.getyCoordinate() + 1];
	}
	if (rob.getHeadsTo() == Robot.south)
	{
	    return place.place[rob.getxCoordinate()][rob.getyCoordinate() - 1];
	}
	if (rob.getHeadsTo() == Robot.west)
	{
	    return place.place[rob.getxCoordinate() - 1][rob.getyCoordinate()];
	}
	// unreachable statement:
	return null;
    }

    /**
     * Method advances one step in the robots heading direction. It paints if
     * robot isPainting is true.
     * 
     * @return True if move is valid, false if there is a wall in next position.
     */
    public boolean forward()
    {
	System.out.println("move forward...");

	if (rob.getHeadsTo() == Robot.north)
	{
	    if (place.place[rob.xCoordinate][rob.yCoordinate - 1]
		    .getGroundType() != MapPiece.land)
	    {
		return false;
	    }
	    rob.setyCoordinate(rob.getyCoordinate() - 1);
	} else if (rob.getHeadsTo() == Robot.east)
	{
	    if (place.place[rob.xCoordinate + 1][rob.yCoordinate]
		    .getGroundType() != MapPiece.land)
	    {
		return false;
	    }
	    rob.setxCoordinate(rob.getxCoordinate() + 1);
	} else if (rob.getHeadsTo() == Robot.south)
	{
	    if (place.place[rob.xCoordinate][rob.yCoordinate + 1]
		    .getGroundType() != MapPiece.land)
	    {
		return false;
	    }
	    rob.setyCoordinate(rob.getyCoordinate() + 1);
	} else if (rob.getHeadsTo() == Robot.west)
	{
	    if (place.place[rob.xCoordinate - 1][rob.yCoordinate]
		    .getGroundType() != MapPiece.land)
	    {
		return false;
	    }
	    rob.setxCoordinate(rob.getxCoordinate() - 1);
	}
	if (rob.isPainting())
	{
	    place.place[rob.getxCoordinate()][rob.getyCoordinate()]
		    .setIsPainted(true);
	}
	return true;
    }

    /**
     * Method advances one step in the robots heading direction. It paints if
     * robot isPainting is true.
     * 
     * @return True if move is valid, false if there is a wall in next position.
     * @author Esteban Ortiz
     */
    public boolean backward()
    {
	int headsTo = rob.getHeadsTo();

	switch (headsTo)
	{
	    case NORTH:

		break;
	    case SOUTH:
		break;

	    case EAST:
		break;

	    case WEST:
		break;
	}

	System.out.println("move backward...");
	return false;
    }

    /**
     * turns robot to left direction from where he heads.
     */
    public void left()
    {
	System.out.println("turn left...");

	if (rob.getHeadsTo() == Robot.north)
	{
	    rob.setHeadsTo(Robot.west);
	} else if (rob.getHeadsTo() == Robot.east)
	{
	    rob.setHeadsTo(Robot.north);
	} else if (rob.getHeadsTo() == Robot.south)
	{
	    rob.setHeadsTo(Robot.east);
	} else if (rob.getHeadsTo() == Robot.west)
	{
	    rob.setHeadsTo(Robot.south);
	}
    }

    /**
     * Turns robot to the right direction from where he heads.
     */
    public void right()
    {
	System.out.println("turn right...");
	if (rob.getHeadsTo() == Robot.north)
	{
	    rob.setHeadsTo(Robot.east);
	} else if (rob.getHeadsTo() == Robot.east)
	{
	    rob.setHeadsTo(Robot.south);
	} else if (rob.getHeadsTo() == Robot.south)
	{
	    rob.setHeadsTo(Robot.west);
	} else if (rob.getHeadsTo() == Robot.west)
	{
	    rob.setHeadsTo(Robot.north);
	}
    }

    /**
     * Picks up object if there is an object in front of him.
     * 
     * @return True if an object was picked up.
     */
    public boolean pickUp()
    {
	rob.setHasObj(true);
	if (rob.getHeadsTo() == Robot.north)
	{
	    if (place.place[rob.xCoordinate][rob.yCoordinate + 1].hasObj)
	    {
		place.place[rob.xCoordinate][rob.yCoordinate + 1]
			.setHasObj(false);
		return true;
	    } else
	    {
		return false;
	    }
	}
	if (rob.getHeadsTo() == Robot.east)
	{
	    if (place.place[rob.xCoordinate + 1][rob.yCoordinate].hasObj)
	    {
		place.place[rob.xCoordinate + 1][rob.yCoordinate]
			.setHasObj(false);
		return true;
	    } else
	    {
		return false;
	    }
	}
	if (rob.getHeadsTo() == Robot.south)
	{
	    if (place.place[rob.xCoordinate][rob.yCoordinate - 1].hasObj)
	    {
		place.place[rob.xCoordinate][rob.yCoordinate - 1]
			.setHasObj(false);
		return true;
	    } else
	    {
		return false;
	    }
	}
	if (rob.getHeadsTo() == Robot.west)
	{
	    if (place.place[rob.xCoordinate - 1][rob.yCoordinate].hasObj)
	    {
		place.place[rob.xCoordinate - 1][rob.yCoordinate]
			.setHasObj(false);
		return true;
	    } else
	    {
		return false;
	    }
	}
	return false;
    }

    /**
     * Puts down object. Precondition: Robot has picked an object.
     * 
     * @return True if object is put down.
     */
    public boolean putDown()
    {
	if (!rob.getHasObj())
	{
	    return false;
	}
	if (!place.place[rob.xCoordinate][rob.yCoordinate].walkable())
	{
	    return false;
	}
	if (rob.getHeadsTo() == Robot.north)
	{
	    place.place[rob.xCoordinate][rob.yCoordinate + 1].setHasObj(true);
	}
	if (rob.getHeadsTo() == Robot.east)
	{
	    place.place[rob.xCoordinate + 1][rob.yCoordinate].setHasObj(true);
	}
	if (rob.getHeadsTo() == Robot.south)
	{
	    place.place[rob.xCoordinate][rob.yCoordinate - 1].setHasObj(true);
	}
	if (rob.getHeadsTo() == Robot.west)
	{
	    place.place[rob.xCoordinate - 1][rob.yCoordinate].setHasObj(true);
	}
	return true;
    }
    
    /**
     * Ejecuta un script a partir a partir de una cadena de texto.
     * 
     * @param ins es el script como cadena de texto a ser ejecutado.
     */
    public void expr(String ins)
    {
	Stack insT = new Stack();
	StringTokenizer tk = new StringTokenizer(ins, "( ) { } \n");
	while (tk.hasMoreTokens())
	{
	    String token = tk.nextToken();
	    System.out.println("token"+token);
	    insT.addElement(token);
	    if (token.equals("if"))
	    {
		// TODO call if methdos
	    } else if (token.equals("repeat"))
	    {
		// TODO call repeath methods
	    } else
	    {
		movementInstructions(token, tk.nextToken());
	    }

	}
    }

    /**
     * Ejecuta las instrucciones que hacen que el robot se mueva.
     * 
     * @param ins
     * @param amount
     */
    public void movementInstructions(String ins, String amount)
    {
	
    System.out.println("head"+rob.getHeadsTo())	;
    int spaces = Integer.parseInt(amount);

	for (int i = 0; i < spaces; i++)
	{
	    if (ins.equals("forward"))
		forward();

	    else if (ins.equals("backward"))
		backward();
	    
	    else if (ins.equals("left"))
		left();

	    else if (ins.equals("right")) 
		right();
	}

    }
}


